﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. 
// See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Actors.Languages;
using System.Threading.Tasks;

namespace System.Threading.Actors
{
    public interface IActorState : IDisposable
    {
        // Actor state interaction
        void Set(string key, object value);
        object Get(string key);
        bool TryGet(string key, out object value);
        void Remove(string key);

        object CallMethod(string methodName, object[] args);

        // State management methods for use by Actor Framework
        Task Flush(); // "Commit"
        bool ChangesPendingForCurrentOperation();
        void ClearChangesForCurrentOperation(); // "Rollback"
        IEnumerable<string> GetAllKeysWithPrefix(string keyPrefix);

        // Pub/sub support
        void Subscribe(IPublicationCallbackContract callerProxy, string eventType);
        void Unsubscribe(IPublicationCallbackContract callerProxy, string eventType);
        void UnsubscribeAll(IPublicationCallbackContract callerProxy);
        void Publish(string eventType, object eventPayload);
        void Publish(string eventType, object eventPayload, params object[] eventPayloadQualifiers);

        // Allows for communications with other actors
        IActorProxy GetActorProxy(string externalActorName, string partitionName = null);
        IActorPromise GetActorProxyAsync(string externalActorName, string partitionName = null);

        // Allow an actor method to determine its own identity
        string GetId();
        string PartitionName { get; }

        // Language support
        void AddLanguagePack(SupportedLanguages language, Func<ILanguagePackage> pack);
        void AddMethod(SupportedLanguages language, string methodName, string methodImpl);

        // Actor creation and deletion
        /// <summary>
        /// Creates a new actor.
        /// </summary>
        /// <param name="actorName">The full name of the new actor (e.g., "fabric:/actor/adhoc/myactor")</param>
        /// <param name="creationString">A series of implementation-specific key-value pairs, separated by semicolons</param>
        /// <param name="numPartitions">How many partitions to support.  Using more than one partition requires specifying a partition name later.  The default is 1.</param>
        /// <returns>true if actor already existed, false otherwise</returns>
        bool CreateActor(string actorName, string creationString, int numPartitions = 1);
        void DeleteActor(string actorName);

        // Configuration
        void Configure(String configurationString);

        // I really don't like putting this on IActorState, especially publicly,
        // but it is critical to achieving lock-free execution.
        SemaphoreSlim AsyncStateLock { get; }

        //public IActorPromise Request(string actorName, string partitionKeyName, string methodName, params object[] parameters);
    }
}
